//
//  vdTexManager.m
//  Void Dead
//
//  Created by Sidney Just on 17.11.09.
//
//  Copyright © 2009 by Sidney Just
//  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
//  documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
//  the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 
//  and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
//  INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
//  PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
//  FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
//  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

#import "vdTexManager.h"
#import "vdMacros.h"

@implementation vdTexManager

#pragma mark -
#pragma mark suffix

- (BOOL)registerSuffix:(NSString *)suffix withClass:(id)_class andSelector:(SEL)selector {
	for(int i=0; i<loaders; i++)
	{
		if([loader[i].suffix isEqualToString:suffix])
			return NO;
	}
	
	loaders += 1;
	loader = (vdTextureLoader *)realloc(loader, loaders*sizeof(vdTextureLoader));
	loader[loaders-1].suffix = [[NSString alloc] initWithString:suffix];
	loader[loaders-1].delegate = _class;
	loader[loaders-1].callback = selector;
	
	return YES;
}


- (void)unregisterSuffix:(NSString *)suffix {
	for(int i=0; i<loaders; i++)
	{
		if([loader[i].suffix isEqualToString:suffix])
		{
			[loader[i].suffix release];
			
			for(int j=i; j<loaders-1; j++)
			{
				loader[j] = loader[j+1];
			}
			
			loaders -= 1;
			loader = (vdTextureLoader *)realloc(loader, loaders*sizeof(vdTextureLoader));
			
			return;
		}
	}
}

- (vdTextureLoader *)getClassForSuffix:(NSString *)str {
	for(int i=0; i<loaders; i++)
	{
		if([str hasSuffix:loader[i].suffix])
		{
			return &loader[i];
		}
	}
	
	return NULL;
}

#pragma mark -
#pragma mark deleting

- (void)deleteTextureNode:(vdTexNode *)aNode {
	for(int i=0; i<count; i++)
	{
		if(aNode == textures[i])
		{	
			int k = [textures[i] retainCount];
			[textures[i] release];
			
			if(k <= 1)
			{
				for(int j=i; j<count-1; j++)
				{
					textures[j] = textures[j+1];
				}
			
				count -= 1;
				textures = (vdTexNode **)realloc(textures, count*sizeof(vdTexNode *));
			}
			
			return;
		}
	}
}

- (void)deleteTexture:(NSString *)aFile {
	for(int i=0; i<count; i++)
	{
		if([aFile isEqualToString:textures[i].name])
		{
			[self deleteTextureNode:textures[i]];
			return;
		}
	}
}

- (int)removeUnusedTextures {
	vdTexNode **nodes = (vdTexNode **)malloc(count*sizeof(vdTexNode *));
	int tCount = count;
	
	for(int i=0; i<count; i++)
	{
		nodes[i] = textures[i];
	}
	
	for(int i=0; i<tCount; i++)
	{
		[self deleteTextureNode:nodes[i]];
	}
	
	for(int i=0; i<count; i++)
	{
		[textures[i] retain];
	}
	
	free(nodes);
	
	return tCount - count;
}

#pragma mark -
#pragma mark Loading

- (vdTexNode *)loadTexture:(NSString *)aFile {	
	for(int i=0; i<count; i++)
	{
		if([aFile isEqualToString:textures[i].name])
		{
			[textures[i] retain];
			return textures[i];
		}
	}
	
	count += 1;
	textures = (vdTexNode **)realloc(textures, count*sizeof(vdTexNode *));
	
	vdTextureLoader *_class = [self getClassForSuffix:aFile];
	
	if(_class)
	{
		textures[count-1] = [[vdTexNode alloc] init];
		textures[count-1].name = [[NSString alloc] initWithString:aFile];
		
		[_class->delegate performSelector:_class->callback withObject:textures[count-1]];
		
	} else {
		textures[count-1] = [[vdTexNode alloc] initWithFile:aFile];
	}
	
	vdLog(@"Loaded texture <%@> into %@", aFile, textures[count-1]);
	
	return textures[count-1];
}

#pragma mark -
#pragma mark Con- Destructor

static vdTexManager *_sharedManager = NULL;

+ (vdTexManager *)sharedManager {
	if(!_sharedManager)
	{
		_sharedManager = [[vdTexManager alloc] init];
	}
	
	return _sharedManager;
}

- (id)init {
	if(!_sharedManager)
	{
		if(self = [super init])
		{
			count = 0;
			textures = (vdTexNode **)malloc(sizeof(vdTexNode *));
			
			loaders = 0;
			loader = (vdTextureLoader *)malloc(sizeof(vdTextureLoader));
		}
		
		_sharedManager = self;
		return self;
	}
	return _sharedManager;
}

- (void)dealloc {
	for(int i=0; i<count; i++)
	{
		int k = [textures[i] retainCount];
		
		for(int j=0; j<k; j++)
			[textures[i] release];
	}
	
	free(textures);
	
	for(int i=0; i<loaders; i++)
	{
		[loader[i].suffix release];
	}
	
	free(loader);
	
	if(self == _sharedManager)
		_sharedManager = NULL;
	
	[super dealloc];
}

@end
